package cn.backpackerxl.easyJDBC.util;


import java.lang.reflect.Field;
import java.util.*;

public final class AddDoubleRule implements JSONParseRule {
    private boolean isArray;
    private boolean isList;
    private boolean isMap;

    @Override
    public boolean evaluate(JSONExpression jsonExpression) {
        boolean eval = false;
        this.isArray = jsonExpression.getField().getType().getTypeName().equals("java.lang.Double[]") || jsonExpression.getField().getType().getTypeName().equals("double[]");
        this.isList = jsonExpression.getTypeName().equals("java.util.List<java.lang.Double>");
        this.isMap = jsonExpression.getTypeName().equals("java.util.Map<java.lang.String, java.lang.Double>");
        if (jsonExpression.getTypeof() == Typeof.$DOUBLE || jsonExpression.getTypeof() == Typeof.DOUBLE || this.isArray || this.isMap || this.isList) {
            this.apply(jsonExpression.getObject(), jsonExpression.getField(), jsonExpression.getJsonObject());
            eval = true;
        }
        return eval;
    }

    @Override
    public void apply(Object entity, Field field, JSONObject obj) {
        try {
            if (this.isArray) {
                Object[] objects = obj.getArrays().stream().map(JSONObject::getDouValue).toArray();
                String ty = BasicUtil.typeName(field);
                Typeof typeof = MatchType.get(ty);
                switch (Objects.requireNonNull(typeof)) {
                    case DOUBLE:
                        Double[] doubles = Arrays.copyOf(objects, objects.length, Double[].class);
                        field.set(entity, doubles);
                        break;
                    case $DOUBLE:
                        double[] arr = new double[objects.length];
                        for (int i = 0; i < arr.length; i++) {
                            arr[i] = (int) objects[i];
                        }
                        field.set(entity, arr);
                        break;
                    default:
                        throw new RuntimeException("parse double[] or Double[] error.");
                }
            } else if (this.isList) {
                List<Double> list = new ArrayList<>();
                this.applyList(obj, list);
                field.set(entity, list);
            } else if (this.isMap) {
                Map<String, Double> map = new HashMap<>();
                this.applyMap(obj, map);
                field.set(entity, map);
            } else {
                field.set(entity, obj.getDouValue());
            }
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public void applyList(JSONObject obj, List<Double> list) {
        for (JSONObject jsonObject : obj.getArrays()) {
            list.add(jsonObject.getDouValue());
        }
    }

    public void applyMap(JSONObject obj, Map<String, Double> map) {
        for (JSONObject object : obj.getArrays()) {
            for (String s : object.getObjValue().keySet()) {
                map.put(s, object.getObjValue().get(s).getDouValue());
            }
        }
    }
}
